//#include <iostream>

#include <math.h>

using namespace std;

#include "vec3.h"



vec3::vec3() : vx(0), vy(0), vz(0)	//sets coordinates to 0
{
}

vec3::vec3(float x, float y, float z) : vx(x), vy(y), vz(z)	//sets coordinates to x,y,z
{

}

vec3::~vec3()
{
	//here be dtor
}

vec3::vec3(const vec3 &that) : vx(that.vx), vy(that.vy), vz(that.vz)
{
}

vec3 &vec3::operator= (const vec3 &that)
{
	this->vx = that.vx;
	this->vy = that.vy;
	this->vz = that.vz;

	return *this;
}

vec3 vec3::operator+ (const vec3 &that) const 
{
	vec3 toRet;
	toRet.vx = this->vx + that.vx;
	toRet.vy = this->vy + that.vy;
	toRet.vz = this->vz + that.vz;
	
	return toRet;
}

vec3 vec3::operator- (const vec3 &that) const 
{
	vec3 toRet;
	toRet.vx = this->vx - that.vx;
	toRet.vy = this->vy - that.vy;
	toRet.vz = this->vz - that.vz;
	
	return toRet;
}

vec3 vec3::operator* (const float &that) const 
{
	vec3 toRet;
	toRet.vx = this->vx * that;
	toRet.vy = this->vy * that;
	toRet.vz = this->vz * that;
	
	return toRet;
}

vec3 vec3::operator/ (const float &that) const 
{
	vec3 toRet;
	toRet.vx = this->vx / that;
	toRet.vy = this->vy / that;
	toRet.vz = this->vz / that;
	
	return toRet;
}

vec3 vec3::cross(const vec3 &that) const
{
	float x = (this->vy * that.vz) - (this->vz * that.vy);
	float y = (this->vz * that.vx) - (this->vx * that.vz);
	float z = (this->vx * that.vy) - (this->vy * that.vx);

	//return vec3(x, y, z);
	return vec3(x,y,z);
}

float vec3::dot(const vec3 &that) const
{
	return (this->vx * that.vx + this->vy * that.vy + this->vz * that.vz);
}

float vec3::cosdot(const vec3 &that) const
{
	float lengthV1 = this->length();
	float lengthV2 = that.length();
	return that.dot(that) / (lengthV1 * lengthV2);
}

vec3 vec3::normalize() const
{
	vec3 temp;
	float len = this->length();

	if (len == 0)
		len = 1;

	temp.vx = this->vx/len;
	temp.vy = this->vy/len;
	temp.vz = this->vz/len;
	return temp;
}

float vec3::length() const
{
	float x2 = this->vx * this->vx;
	float y2 = this->vy * this->vy;
	float z2 = this->vz * this->vz;

	return sqrt(x2 + y2 + z2);
}

float vec3::distance(const vec3 &that) const
{
	float x2 = this->vx - that.vx;
	float y2 = this->vy - that.vy;
	float z2 = this->vz - that.vz;

	x2 *= x2;
	y2 *= y2;
	z2 *= z2;

	return sqrt(x2 + y2 + z2);
}

ostream &operator<< (ostream &out, const vec3 &that)
{
	out << "X: " << that.vx << " Y: " << that.vy << " Z: " << that.vz;
	return out;
}
